#pragma once


#include <iostream>
#include <memory>
#include <string>
#include <functional>
#include <thread>
#include <mutex>
#include <vector>
#include <stdint.h>

#include "asio.hpp"
#include "nwbaseconnection.h"
#include "networkutil_common_def.h"


namespace NetworkUtil {

class Session;
class TcpServer;

void NetworkUtil_DllExport setRecvCallbackFunc(std::function<void(const std::string& strDataBuf, NetworkUtil::Session* pSession)> pfnRecvCallback);

class NetworkUtil_DllExport Session : public std::enable_shared_from_this<Session>
{
public:
    Session(uint32_t ui32BufMaxSize, asio::ip::tcp::socket socket, NetworkUtil::TcpServer* pSrvHandler);
    ~Session();

    void start();
    void stop();

    uint32_t read(char* pDataBuf, uint32_t ui32DataBufLen);
    uint32_t read(std::string& strDataBuf);

    uint32_t write(const char* pDataBuf, uint32_t ui32DataBufLen);
    uint32_t write(const std::string& strDataBuf);

    std::string remoteInfo();

private:
    void onRecvDataProcess();
    void clientLostConnection();

private:
    volatile bool m_bRunning = false;
    volatile bool m_bConnected = false;
    std::shared_ptr<std::thread> m_sp4thRecv = nullptr;

    uint32_t m_ui32BufMaxSize = 1024;
    asio::ip::tcp::socket m_objSocket;
    NetworkUtil::TcpServer* m_pSrvHandler = nullptr;
};

class NetworkUtil_DllExport TcpServer : public BaseConnection
{
public:
    TcpServer() {}
    TcpServer(const ConnectionConfigInfo& stConnCfgInfo);
    ~TcpServer() override;

    void init() override;
    void deinit() override;

    void removeClient(NetworkUtil::Session* pSession);

private:
    void onAsyncAcceptBusinessProcess();
    void onSyncAcceptBusinessProcess();

private:
    std::shared_ptr<asio::ip::tcp::acceptor> m_sp4ObjAcceptor = nullptr;
    std::shared_ptr<std::thread> m_sp4thAcceptBusiness = nullptr;

    std::mutex m_mt4Sessions;
    std::vector<std::shared_ptr<NetworkUtil::Session> > m_vt4spSessions;
};


} // namespace NetworkUtil


